package reflect_extend

import (
	"reflect"
)

// 结构体内部字段首字母小写，并且是取地址访问 ,可以使用下面的方法来设置  ,直接作用于原结构体
// s:结构体指针
// filed:字段名称
// val:值
func SetPtrFiled(s interface{}, filed string, val interface{}) error {
	v := GetPtrFiled(s, filed)
	rv := reflect.ValueOf(val)
	if v.Kind() != reflect.Ptr {
		panic("s 必须是指针,如果传入的类型是interface{}请检查原始类型是否是指针")
	}
	v.Set(rv)
	return nil
}

// 结构体内部字段首字母小写，并且是非取地址 ,可以使用下面的方法来设置
// s:结构体指针
// filed:字段名称
// val:值
func SetNotPtrFiled(s interface{}, filed string, val interface{}) error {
	v := GetPtrUnExportedField(s, filed)
	if v.Kind() != reflect.Ptr {
		panic("s 必须是指针,如果传入的类型是interface{}请检查原始类型是否是指针")
	}
	rv := reflect.ValueOf(val)
	v.Set(rv)
	return nil
}

// 给指针赋值
// s:指针
// val:值
func SetPtrValue(s interface{}, val interface{}) {
	v := reflect.ValueOf(s)
	if v.Kind() != reflect.Ptr {
		panic("s 必须是指针")
	}
	elem := v.Elem()
	if !elem.CanSet() {
		panic("s 不能被赋值,请检查是否是指针,如果传入的类型是interface{}请检查原始类型是否是指针")
	}

	rv := reflect.ValueOf(val)
	elem.Set(rv)
}

// 将非指针类型转换为指针类型
func ToPtr(v interface{}) interface{} {
	if IsPtr(v) {
		return v
	}
	newPtr := reflect.New(reflect.TypeOf(v)).Interface()
	//给指针赋值
	SetPtrValue(newPtr, v)
	return newPtr
}

//
